标签: 应用架构
微服务指南
微服务架构模式是一种将单个应用程序开发为一套小型服务的方法,每个服务都在自己的进程中运行,并通过轻量级机制(通常是 HTTP 资源 API)进行通信。这些服务围绕业务功能构建,并且可以通过全自动部署机制独立部署。这些服务的集中管理极少,可以使用不同的编程语言编写,并使用不同的数据存储技术。虽然它们的优势使它们在过去几年中非常流行,但它们也带来了分布式增加、一致性减弱的成本,并且需要成熟的运营管理。
微服务
“微服务架构”一词在过去几年中兴起,用于描述一种将软件应用程序设计为一套可独立部署的服务的特定方式。虽然没有对这种架构风格的精确定义,但在围绕业务能力的组织、自动化部署、端点智能以及语言和数据的去中心化控制方面,有一些共同的特征。
微前端
做好前端开发很难。扩展前端开发以使多个团队能够同时在一个大型复杂产品上工作则更加困难。在本文中,我们将描述一种将前端巨石分解成许多更小、更易于管理的部分的最新趋势,以及这种架构如何提高前端代码团队的工作效率。除了讨论各种优势和成本之外,我们还将介绍一些可用的实现选项,并将深入探讨一个完整的示例应用程序来演示该技术。
使用已建立的 UI 模式对 React 应用程序进行模块化
已建立的 UI 模式在前端开发领域往往没有得到充分利用,尽管它们在解决 UI 设计中的复杂问题方面已被证明是有效的。本文探讨了已建立的 UI 构建模式在 React 世界中的应用,并通过重构旅程代码示例展示了其优势。重点是如何通过分层架构来组织 React 应用程序,以提高响应能力和未来的变更。
分布式系统模式目录
分布式系统对编程提出了特殊的挑战。它们通常要求我们拥有多个数据副本,这些副本需要保持同步。然而,我们不能依赖处理节点可靠地工作,网络延迟很容易导致不一致。尽管如此,许多组织仍然依赖一系列核心分布式软件来处理数据存储、消息传递、系统管理和计算能力。这些系统面临着共同的问题,它们使用类似的解决方案来解决这些问题。2020 年,Unmesh Joshi 开始收集这些解决方案作为模式,并在开发过程中将它们发布在这个网站上。2023 年,这些模式被收录在《分布式系统模式》一书中。本页链接到每个模式的简要摘要,并提供指向 oreilly.com 上在线电子书出版物相关章节的深层链接。
无服务器架构
无服务器架构是结合了第三方“后端即服务”(BaaS) 服务的应用程序设计,和/或包含在“函数即服务”(FaaS) 平台上的托管、临时容器中运行的自定义代码。通过使用这些理念以及单页应用程序等相关理念,此类架构消除了对传统始终在线服务器组件的大部分需求。无服务器架构可以显著降低运营成本、复杂性和工程交付周期,但代价是增加了对供应商依赖以及相对不成熟的支持服务的依赖。
功能切换(又称功能标志)
功能切换(通常也称为功能标志)是一种强大的技术,允许团队在不更改代码的情况下修改系统行为。它们属于各种使用类别,在实现和管理切换时,务必考虑这种分类。切换会引入复杂性。我们可以通过使用智能切换实现实践和适当的工具来管理我们的切换配置,从而控制这种复杂性,但我们也应该致力于限制系统中切换的数量。
面向领域的观测性
软件系统中的观测性一直很有价值,在这个云计算和微服务时代更是如此。然而,我们添加到系统中的观测性往往在本质上是相当低级的技术,而且它似乎常常需要在我们的代码库中充斥着对各种日志记录、检测和分析框架的粗糙、冗长的调用。本文描述了一种模式,它可以清理这种混乱,并允许我们以一种干净、可测试的方式添加与业务相关的观测性。
关于敏捷和架构的播客
Ryan Lockard(敏捷起义)邀请我与 Rebecca Wirfs-Brock 一起参加关于敏捷项目架构的播客对话。Rebecca 开发了责任驱动设计,这在我职业生涯初期对我产生了很大的影响。我们讨论了如何定义架构、测试对架构的影响、领域模型的作用、准备什么样的文档以及需要预先完成多少架构工作。
演进式数据库设计
在过去十年中,我们开发并完善了许多技术,允许数据库设计随着应用程序的发展而发展。这对敏捷方法论来说是一项非常重要的能力。这些技术依赖于将持续集成和自动化重构应用于数据库开发,以及 DBA 和应用程序开发人员之间的密切协作。这些技术适用于预生产系统和已发布系统,适用于全新项目以及遗留系统。
重构模块依赖关系
随着程序规模的增长,将其拆分成模块非常重要,这样您就不需要了解所有内容就可以进行小的修改。这些模块通常可以由不同的团队提供,并动态组合。在这篇重构文章中,我使用表示层-领域层-数据层对一个小程序进行了拆分。然后,我重构了这些模块之间的依赖关系,以引入服务定位器和依赖注入模式。这些模式适用于不同的语言,但看起来不同,因此我将以 Java 和无类 JavaScript 风格展示这些重构。
重构访问外部服务的代码
当我编写处理外部服务的代码时,我发现将访问代码分离到单独的对象中很有价值。在这里,我将展示如何将一些凝固的代码重构为此分离的常见模式。
六边形架构和 Rails
我和我的同事 Badri 之间关于六边形架构及其在 Rails 应用程序中的作用的对话视频。在第一个视频中,我们讨论了六边形架构的含义,以及这如何导致为持久性框架选择 Active Record 和 Data Mapper 模式。在第二个视频中,我们将更广泛地讨论 Rails 在应用程序中应该扮演的架构角色——您应该将其视为一个平台,还是一套组件。
双栈 CMS
我们使用流行的内容管理系统 (CMS) 构建了许多内容丰富的网站。最近的一个项目涉及一家全球制造商的营销网站,该网站需要具有高可用性和流量需求的复杂交互式内容。我们的应对措施是应用编辑-发布分离模式,并为内容创建和交付构建两个不同的软件堆栈。在本演示文稿中,您可以看到此架构的概述,以及我们对堆栈之间集成问题的响应、提供实时站点的安全预览以及处理系统的演进和扩展。
实际应用中的 DIP
依赖倒置原则 (DIP) 自 90 年代初就已经存在,但即使如此,在解决问题的过程中似乎也很容易忘记它。在给出一些定义之后,我将介绍我在实际项目中个人使用过的 DIP 的一些应用,以便您从中得出自己的结论。
LMAX 架构
LMAX 是一个全新的零售金融交易平台。因此,它必须以低延迟处理大量交易。该系统构建在 JVM 平台之上,核心是一个业务逻辑处理器,它可以在单个线程上每秒处理 600 万个订单。业务逻辑处理器完全在内存中运行,并使用事件溯源。业务逻辑处理器被 Disruptor 包围——Disruptor 是一个并发组件,它实现了一个无需锁即可运行的队列网络。在设计过程中,团队得出结论,最近使用队列的高性能并发模型的方向与现代 CPU 设计根本不一致。
企业软件开发模式
对各种企业软件开发模式编目工作的个人调查。
Ruby Rogues 节目讨论企业应用架构模式
Ruby Rogues 是一个很受欢迎的播客,由一个固定的小组讨论 Ruby 编程社区中的话题。他们有一个固定的读书俱乐部,最近选择了企业应用架构模式作为他们的特色书籍。因此,他们邀请我作为嘉宾参加他们的节目,讨论这本书及其描述的模式,特别是这些模式与 Rails 框架之间有趣的关系。
控制反转容器和依赖注入模式
在 Java 社区中,涌现出大量轻量级容器,它们有助于将来自不同项目的组件组装成一个 cohesive 的应用程序。这些容器的基础是它们执行连接的通用模式,他们将这个概念称为非常通用的名称“控制反转”。在本文中,我将深入探讨这种模式是如何工作的,它有一个更具体的名称叫做“依赖注入”,并将其与服务定位器替代方案进行对比。选择哪种方式并不重要,重要的是将配置与使用分离的原则。
依赖组合
基于对传统的基于框架的依赖注入的失望,我采用了一种组合策略,利用部分应用将上下文注入到模块中。当与作为设计过程的测试驱动开发以及对函数而非类的关注相结合时,模块可以保持清晰、干净,并且基本上没有意外的耦合。
错误的架构
《软件开发》杂志将我的著作《企业应用架构模式》第 7 章(分布式策略)改编成了一篇文章发表在他们的杂志上。我怀疑他们喜欢它是因为它的语气和其中包含的分布式对象设计第一定律。
关注事件
一个模式叙述,着眼于如何将事件作为系统如何运行和与对等方协作的焦点。总结了如何表示事件、如何使用事件在系统之间集成以及在系统架构中使用事件溯源。
GUI 架构
GUI 架构如何演变的历史概述,特别关注不同群体多年来如何看待模型-视图-控制器。从历史的角度来看,它与我的演示模式相关联。
组织表示逻辑
用户界面中模式的叙述性概述。讨论如何以及为什么要将领域逻辑与表示分离,以及如何分离和同步数据层。
《构建演进式架构》前言
最近,我的同事 Neal Ford、Rebecca Parsons 和 Pat Kua 写了一本名为“构建演进式架构”的书。我很荣幸他们邀请我为这本书写序。
正视康威定律的力量
康威定律(由 Melvin Conway 于 1968 年提出)指出,系统的设计受其设计者的沟通模式的限制。Birgitta、Mike、James 和我讨论了这一原则的含义,以及我们在职业生涯中是如何看到它发挥作用的。我们讨论了它对微服务概念的影响、与业务能力保持一致的重要性,以及逆康威策略的作用。
应用边界
软件开发中尚未解决的问题之一是确定一块软件的边界是什么。(浏览器是操作系统的一部分吗?)许多面向服务架构的支持者认为应用程序正在消失——因此未来的企业软件开发将是关于将服务组装在一起。
我认为应用程序不会消失,原因与应用程序边界如此难以划定的原因相同。本质上,应用程序是社会构建的
CQRS
CQRS 代表命令查询职责分离。这是我第一次听到 Greg Young 描述的一种模式。其核心是,您可以使用与读取信息所用模型不同的模型来更新信息。对于某些情况,这种分离可能很有价值,但请注意,对于大多数系统来说,CQRS 会增加风险复杂性。
断路器
软件系统通常会远程调用在不同进程中运行的软件,这些软件可能位于网络上的不同机器上。内存内调用和远程调用之间的一大区别是,远程调用可能会失败,或者在达到某个超时限制之前一直挂起而没有响应。更糟糕的是,如果您有许多调用者在一个没有响应的提供程序上,那么您可能会耗尽关键资源,从而导致跨多个系统的级联故障。Michael Nygard 在他的优秀著作《发布它》中推广了断路器模式,以防止这种灾难性的级联。
断路器背后的基本思想非常简单。您将受保护的函数调用包装在一个断路器对象中,该对象监视故障。一旦故障达到某个阈值,断路器就会跳闸,并且对断路器的所有进一步调用都会返回错误,而根本不会进行受保护的调用。通常,如果断路器跳闸,您还需要某种监视器警报。
上下文验证
在我的写作过程中,我一直打算写一些关于验证的材料。这是一个容易引起很多困惑的领域,最好是对一些行之有效的技术进行一些可靠的描述。然而,生活中充满了要写的东西,远远超过了时间允许的范围。
康威定律
几乎所有我喜欢的软件架构从业者都对该领域中的任何一般性定律深表怀疑。好的软件架构是非常依赖于上下文的,它分析的权衡在各种环境中都有不同的解决方案。但如果说有一件事他们都同意的话,那就是康威定律的重要性和力量。它足够重要,可以影响我遇到的每一个系统,而且足够强大,以至于如果你试图与之抗衡,你注定会失败。
领域驱动设计
领域驱动设计是一种软件开发方法,其核心是围绕对领域的过程和规则有深入了解的领域模型进行编程。这个名字来自 Eric Evans 2003 年出版的一本书,该书通过一系列模式描述了这种方法。从那时起,一个从业者社区进一步发展了这些想法,催生了各种其他书籍和培训课程。这种方法特别适用于需要组织大量经常混乱的逻辑的复杂领域。
预先读取派生
我在QCon 旧金山大会上参加的一个有趣的演讲是由Greg Young做的,内容是关于他在最近一个系统中使用的特定架构。Greg 是领域驱动设计的忠实粉丝,在这种情况下,需要将其与必须处理高交易率并向大量用户提供数据的系统一起使用。我发现他的设计有很多有趣的地方,特别是 er>事件溯源,但在这篇文章中,我只想谈谈一个方面——我称之为预先读取派生。
编辑发布分离
在过去一年左右的时间里,在我与 Thoughtworks 项目团队的对话中,一个经常出现的主题是内容管理系统 (CMS) 日益增长的影响。它们通常不被认为是有帮助的,事实上,有明显的迹象表明,它们正在成为一种令人担忧的侵入性工具——被用于超出其核心目的的范围,从而阻碍了整体开发。
在其他令人恼火的事情中,一个常见的缺陷是它们为每篇文章保留一个副本。此单个副本在创建内容时进行编辑,并发布给读者(通常在某种状态更改标志上)。
企业应用
在本世纪初,我开始写我的书《企业应用架构模式》。在写这本书时,我遇到的一个问题是如何给它命名,或者更确切地说,如何称呼我正在写的这类软件系统。我一直都很清楚,我的软件开发经验一直专注于一种特定形式的软件——比如医疗保健记录、外汇交易、工资单和租赁会计。这些与打印机、游戏、飞行控制软件或电话交换机中的嵌入式软件截然不同。我需要一个名称来描述这类系统,并最终确定了“企业应用”一词。
企业架构
就在最近,我在亚马逊上收到了一些关于《企业应用架构模式》的差评,因为书中没有关于企业架构的内容。当然,这有一个很好的理由——这本书是关于企业*应用*架构的,即如何设计企业应用。企业架构是另一个主题,即如何将企业中的多个应用组织成一个连贯的整体。
事件海报
这是一种我遇到过几次的应用风格。该应用主要是一个报表应用,它为用户提供有关某事物状态的实时信息。它是一个主动应用,因为用户可以控制他们正在查看的内容,他们能够深入到特定区域,并通常可以操作他们的显示;然而,它仍然至少主要是一个只读应用。
说明性架构
加深我们对软件系统理解的一个问题是,我们没有看到足够的例子。在许多专业学科中,人们通过观察已经完成的事情来学习。例子是灵感、好主意的来源,也是困难的警告。很长一段时间以来,以这种方式学习软件一直要困难得多。
定长字符串
看看大多数在应用程序编程语言和关系数据库之间进行通信的库,你会注意到它们将数据库中的字符串类型(char 或 varchar)映射到编程语言中的字符串类型。简单、明显,但也许是错误的。
内部可编程性
我正在编程,想在我当前输入的位置上方添加一个空行。我使用的编辑器没有内置此功能,而我最终非常想要这个功能。我快速搜索了一下谷歌,找到几行代码,将它们粘贴到我的启动文件中,执行它们,瞧,我现在可以用一个按键在上面创建空行了。只花了几分钟,我不必安装任何插件,也不必重新启动编辑器——这对 emacs 用户来说是日常工作。
控制反转
控制反转是你在扩展框架时经常遇到的一种常见现象。事实上,它通常被视为框架的一个定义特征。
关键接口
软件开发团队发现,如果他们尽可能频繁地集成他们的工作,生活会轻松很多。他们还发现,经常发布到生产环境中很有价值。但是团队不想向用户公开半成品的功能。处理这种紧张局势的一个有用技巧是构建所有后端代码,集成,但不构建用户界面。该功能可以集成和测试,但 UI 会一直保留到最后,直到像拱顶石一样,它被添加到完成该功能中,向用户展示它。
分层原则
在过去的几天里,我一直在挪威参加由吉米·尼尔森主持的企业软件研讨会。在研讨会期间,我们举行了一个会议,会上我们提出并投票表决了一系列设计原则。
本地 DTO
如果你一直在关注我的同事 ThoughtBloggers,你就会知道,我的一个笨蛋机器人似乎烧坏了保险丝,澳大利亚的阳光显然烤焦了这些瑞典模特。
乔恩对数据传输对象感到恼火,但 DTO 并不是一件坏事,就像任何模式一样,它们在某些情况下很有用。模式总是有两部分:如何和何时。你不仅需要知道如何实现它们,还需要知道何时使用它们,何时不使用它们。
锁定成本
在我最近的客户服务中,我预见到无服务器架构是一个完美的选择。然而,采用无服务器架构的想法并没有得到我们客户的认可,因为他们担心厂商锁定。对于零售商来说,这是一个有趣的时期,因为留在 AWS 可能意味着亚马逊作为另一家零售企业将获得竞争优势。考虑到不支持竞争对手的想法,我的客户有兴趣确保我们选择的解决方案可以完全移植到其他云厂商。
内存映像
当人们启动一个企业应用时,最早的问题之一是“我们如何与数据库对话”。如今,他们可能会问一个稍微不同的问题:“我们应该使用什么样的数据库——关系型数据库还是这些 NoSQL 数据库?”但还有另一个问题需要考虑:“我们是否应该使用数据库?”
对 ORM 的憎恨
几个月前,当我在伦敦参加 QCon 大会时,似乎每场演讲都包含了一些对对象/关系映射 (ORM) 工具的尖刻评论。我想我应该更仔细地阅读发送给演讲者的会议电子邮件,毫无疑问,其中有一些内容告诉我们所有人,每 45 分钟至少要对 ORM 表示一次蔑视。但正如你所知,我想对这种对 ORM 的憎恨进行一些反驳——因为我认为其中很多都是不必要的。
多语言持久化
2006 年,我的同事尼尔·福特创造了多语言编程一词,以表达应用应该用多种语言编写,以利用不同语言适合解决不同问题的优势。复杂的应用结合了不同类型的问题,因此为工作选择合适的语言可能比试图将所有方面都纳入一种语言更有效率。
在过去几年中,人们对新语言,特别是函数式语言的兴趣激增,我经常想花些时间研究一下 Clojure、Scala、Erlang 等语言。但我的时间有限,我正在优先考虑另一个更重大的转变,即数据库解冻。第一批客户和其他联系人已经开始提供这方面的服务,前景十分诱人。我可以自信地说,如果你要启动一个新的战略性企业应用,你不应该再假设你的持久化应该是关系型的。关系型数据库可能是正确的选择——但你应该认真考虑其他选择。
表示域数据分层
模块化信息丰富的程序最常见的方法之一是将其分为三大层:表示层(UI)、域逻辑层(又称业务逻辑层)和数据访问层。因此,你经常看到 Web 应用被分为 Web 层(了解如何处理 HTTP 请求和呈现 HTML)、业务逻辑层(包含验证和计算)和数据访问层(负责解决如何在数据库或远程服务中管理持久数据)。
表示域分离
我发现并遵循的最有用的设计原则之一是,在程序的表示方面(用户界面)和其余功能之间保持良好的分离。多年来,在我见过这样做的案例中,我看到了很多好处
已发布接口
“*已发布接口*”是我使用的一个术语(首先是在《重构》中),指的是在其定义的代码库之外使用的类接口。因此,它在 Java 中的含义比 public 更广泛,实际上甚至比 C# 中的非内部 public 更广泛。在为 IEEE 软件撰写的专栏中,我认为已发布和公共之间的区别实际上比公共和私有之间的区别更重要。
报表数据库
大多数企业应用都使用数据库来存储持久数据。该数据库支持应用状态的操作更新,以及用于决策支持和分析的各种报表。然而,操作需求和报表需求通常有很大差异——对架构和数据访问模式的要求不同。当发生这种情况时,将报表需求分离到一个报表数据库中通常是一个明智的选择,该数据库获取基本操作数据的副本,但以不同的架构表示它。
请求流映射
与我在 Thoughtworks 的同事们在一起,你很快就会觉得,唯一好的企业服务总线 (ESB) 就是一个死的 ESB。吉姆·韦伯将它们称为错误的意大利面条盒。因此,听到试图将它们从不需要它们的系统中移除的故事并不少见。
资源池
许多程序需要使用创建和维护成本高昂的资源。数据库连接和线程就是例子。资源池提供了一种管理这些资源的好方法。
牺牲式架构
你正坐在会议室里,思考着你的团队在过去几年里一直在开发的代码。你已经做出了决定,你现在能做的最好的事情就是扔掉所有这些代码,在一个全新的架构上重建。这让你如何看待那些注定要被淘汰的代码,如何看待你花在上面的时间,如何看待你很久以前做出的那些决定?
无服务器
无服务器架构是基于互联网的系统,其中应用程序开发不使用通常的服务器进程。相反,它们完全依赖于第三方服务、客户端逻辑和服务托管的远程过程调用 (FaaS) 的组合。
软件组件
自从我进入这个行业以来,将软件开发从费力地编写代码转变为通过简单地组装组件来构建强大的系统的想法一直是一个目标。这是一个有时可以看到但从未真正实现的目标——尽管许多技术都悬挂着工业重用的诱人前景。
静态替换
当我听我们的开发团队谈论他们的工作时,一个共同的主题是他们不喜欢静态的东西。通常,我们会看到常见的服务或组件保存在具有静态初始化器的静态变量中。静态变量(在大多数语言中)的一个大问题是,你不能使用多态性用一个实现替换另一个实现。这让我们很头疼,因为我们非常喜欢测试——而为了测试好,能够用服务存根替换服务非常重要。
绞杀榕应用
当我和辛迪去澳大利亚时,我们在昆士兰海岸的雨林中待了一段时间。这个地区的自然奇观之一是巨大的绞杀榕。它们在树的上枝发芽,逐渐向下生长,直到扎根于土壤中。经过许多年,它们长成了奇妙而美丽的形状,同时绞杀并杀死了作为它们宿主的树木。
沉没成本驱动架构
我发现这是一种可悲的常见架构风格。你的公司购买了一些非常昂贵的基础设施软件。然后,你被告知即使它不适合项目并且会给你带来额外的工作,你也必须在项目中使用它。在你为它支付了那么多钱之后,你不想让它白白浪费,对吧?
跨媒体应用
在过去几年中,移动应用程序一直是软件开发中的热门话题。像许多软件交付公司一样,Thoughtworks 收到了许多客户要求我们为他们构建移动应用程序的请求。然而,大多数情况下,当一家公司要求我们(或任何人)构建移动应用程序时,他们一开始就走错了路。我认为,在大多数情况下,即使你想让用户与移动设备进行交互,你也应该永远不要考虑构建移动应用程序。相反,你需要考虑构建一个可以在多种设备上呈现的单一应用程序:移动设备、台式机、平板电脑——或者你的用户可能使用的任何设备。
无事务
几年前,我和我的两个朋友聊天,他们在 eBay 工作。听到人们在高流量网站上使用的技术总是很有趣,但也许最有趣的花絮之一是 eBay 几乎从不使用数据库事务。
用户自定义字段
软件系统中的一项常见功能是允许用户在数据结构中定义自己的字段。以地址簿为例——你可能想添加很多东西。随着每天都有新的社交网络出现,用户可能希望为他们的联系人添加一个 Bunglr ID 的新字段。